package com.shi.service;

import com.alibaba.fastjson.JSONObject;
import com.shi.entity.DiscussPost;
import com.shi.utils.CommunityConstant;
import org.elasticsearch.action.delete.DeleteRequest;
import org.elasticsearch.action.delete.DeleteResponse;
import org.elasticsearch.action.index.IndexRequest;
import org.elasticsearch.action.index.IndexResponse;
import org.elasticsearch.action.search.SearchRequest;
import org.elasticsearch.action.search.SearchResponse;
import org.elasticsearch.client.Request;
import org.elasticsearch.client.RequestOptions;
import org.elasticsearch.client.RestHighLevelClient;
import org.elasticsearch.common.unit.TimeValue;
import org.elasticsearch.common.xcontent.XContentType;
import org.elasticsearch.index.query.MultiMatchQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.rest.RestStatus;
import org.elasticsearch.search.SearchHit;
import org.elasticsearch.search.builder.SearchSourceBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightBuilder;
import org.elasticsearch.search.fetch.subphase.highlight.HighlightField;
import org.elasticsearch.search.sort.SortOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.data.domain.Page;
import org.springframework.stereotype.Service;

import java.io.IOException;
import java.util.*;
import java.util.concurrent.TimeUnit;

/**
 * @author 石泉
 * @version 1.0
 * @date 21/08/24 16:53
 */
@Service
public class ElasticsearchService implements CommunityConstant {

    private static final Logger LOGGER = LoggerFactory.getLogger(ElasticsearchService.class);

    @Autowired
    @Qualifier("restHighLevelClient")
    private RestHighLevelClient client;

    public void saveDiscussPost(DiscussPost post){
        IndexRequest request = new IndexRequest(INDEX_POST);
        request.id(""+post.getId()).timeout("1s");
        request.source(JSONObject.toJSONString(post), XContentType.JSON);
        try {
            IndexResponse index = client.index(request, RequestOptions.DEFAULT);
            if (!(index.status() == RestStatus.CREATED || index.status() == RestStatus.OK) ){
                throw new RuntimeException("文档添加失败");
            }
        } catch (IOException e) {
            LOGGER.error("文档添加失败: "+e.getMessage());
        }
    }

    public void deleteDiscussPost(int id){
        DeleteRequest request = new DeleteRequest(INDEX_POST);
        request.id(""+id).timeout("1s");
        try {
            DeleteResponse delete = client.delete(request, RequestOptions.DEFAULT);
            if (delete.status() != RestStatus.OK) {
                throw new RuntimeException("文档删除失败");
            }
        } catch (IOException e) {
            LOGGER.error("文档删除失败: "+e.getMessage());
        }
    }

    public  Map<String, Object> searchDiscussPost(String keyword,int offset,int limit) {
        SearchRequest searchRequest = new SearchRequest(INDEX_POST);
        // 构建搜索的条件
        SearchSourceBuilder sourceBuilder = new SearchSourceBuilder();

        // 分页
        sourceBuilder.from(offset);
        sourceBuilder.size(limit);

        // 查询条件 可以使用 QueryBuilders 工具来实现
        MultiMatchQueryBuilder multiMatchQueryBuilder = QueryBuilders.multiMatchQuery(keyword, "content", "title");
        sourceBuilder.query(multiMatchQueryBuilder).sort("type", SortOrder.DESC).sort("score",SortOrder.DESC).sort("createTime",SortOrder.DESC);
        sourceBuilder.timeout(new TimeValue(60, TimeUnit.SECONDS));

        // 高亮
        HighlightBuilder highlightBuilder = new HighlightBuilder();
        highlightBuilder.field("title").field("content").preTags("<em>").postTags("</em>");
        sourceBuilder.highlighter(highlightBuilder);

        // 搜索
        searchRequest.source(sourceBuilder);
        SearchResponse searchResponse = null;
        try {
            searchResponse = client.search(searchRequest, RequestOptions.DEFAULT);
        } catch (IOException e) {
            LOGGER.error("文档搜索失败: "+e.getMessage());
        }

        List<DiscussPost> list = new ArrayList<>();
        for (SearchHit hit : searchResponse.getHits().getHits()) {
            DiscussPost post = new DiscussPost();
            Map<String, Object> sourceAsMap = hit.getSourceAsMap();

            post.setId(Integer.valueOf(sourceAsMap.get("id").toString()));
            post.setUserId(Integer.valueOf(sourceAsMap.get("userId").toString()));
            post.setTitle(sourceAsMap.get("title").toString());
            post.setContent(sourceAsMap.get("content").toString());
            post.setStatus(Integer.valueOf(sourceAsMap.get("status").toString()));
            post.setCreateTime(new Date(Long.valueOf(sourceAsMap.get("createTime").toString())));
            post.setCommentCount(Integer.valueOf(sourceAsMap.get("commentCount").toString()));

            // 处理高亮显示的内容
            HighlightField titleField = hit.getHighlightFields().get("title");
            if (titleField != null) {
                post.setTitle(titleField.getFragments()[0].toString());
            }

            HighlightField contentField = hit.getHighlightFields().get("content");
            if (contentField != null) {
                post.setContent(contentField.getFragments()[0].toString());
            }
            list.add(post);
        }
        Map<String, Object> map = new HashMap<>();
        map.put("list",list);
        map.put("count",searchResponse.getHits().getTotalHits().value);

        return map;
    }
}
